#include "crypt_errno.h"
#include "crypt_eal_provider.h"
#include "crypt_eal_implprovider.h"
#include "provider_impl.h"

#define KAE_DEFAULT_ATTR "provider=KAE"

static const CRYPT_EAL_AlgInfo kaeMds[] = {
    {CRYPT_MD_MD5, kaeMd, KAE_DEFAULT_ATTR},
    {CRYPT_MD_SM3, kaeMd, KAE_DEFAULT_ATTR},
    {CRYPT_MD_SHA1, kaeMd, KAE_DEFAULT_ATTR},
    {CRYPT_MD_SHA256, kaeMd, KAE_DEFAULT_ATTR},
    {CRYPT_MD_SHA224, kaeMd, KAE_DEFAULT_ATTR},
    {CRYPT_MD_SHA384, kaeMd, KAE_DEFAULT_ATTR},
    {CRYPT_MD_SHA512, kaeMd, KAE_DEFAULT_ATTR},
    CRYPT_EAL_ALGINFO_END
};

static const CRYPT_EAL_AlgInfo kaeModes[] = {
    {CRYPT_CIPHER_SM4_ECB, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_SM4_CBC, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_SM4_CTR, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_SM4_XTS, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_SM4_OFB, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES128_ECB, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES128_CBC, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES128_CTR, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES128_OFB, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES192_ECB, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES192_CBC, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES192_CTR, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES192_OFB, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES256_ECB, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES256_CBC, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES256_CTR, kaeMode, KAE_DEFAULT_ATTR},
    {CRYPT_CIPHER_AES256_OFB, kaeMode, KAE_DEFAULT_ATTR},
    CRYPT_EAL_ALGINFO_END
};

static const CRYPT_EAL_AlgInfo kaeMgmt[] = {
    {CRYPT_PKEY_RSA, kaeRsaMgmt, KAE_DEFAULT_ATTR},
    {CRYPT_PKEY_DH, kaeDhMgmt, KAE_DEFAULT_ATTR},
    CRYPT_EAL_ALGINFO_END
};

static const CRYPT_EAL_AlgInfo kaeAsymCiphers[] = {
    {CRYPT_PKEY_RSA, kaeRsaCipher, KAE_DEFAULT_ATTR},
    CRYPT_EAL_ALGINFO_END
};

static const CRYPT_EAL_AlgInfo kaeKeyExch[] = {
    {CRYPT_PKEY_DH, kaeDhExch, KAE_DEFAULT_ATTR},
    CRYPT_EAL_ALGINFO_END
};

static const CRYPT_EAL_AlgInfo kaeSigns[] = {
    {CRYPT_PKEY_RSA, kaeRsaSign, KAE_DEFAULT_ATTR},
    CRYPT_EAL_ALGINFO_END
};

static int32_t CRYPT_EAL_DefaultProvQuery(void *provCtx, int32_t operaId, const CRYPT_EAL_AlgInfo **algInfos)
{
    (void) provCtx;
    int32_t ret = CRYPT_SUCCESS;
    switch (operaId) {
        case CRYPT_EAL_OPERAID_SYMMCIPHER:
            *algInfos = kaeModes;
            break;
        case CRYPT_EAL_OPERAID_KEYMGMT:
            *algInfos = kaeMgmt;
            break;
        case CRYPT_EAL_OPERAID_SIGN:
            *algInfos = kaeSigns;
            break;
        case CRYPT_EAL_OPERAID_ASYMCIPHER:
            *algInfos = kaeAsymCiphers;
            break;
        case CRYPT_EAL_OPERAID_KEYEXCH:
            *algInfos = kaeKeyExch;
            break;
        case CRYPT_EAL_OPERAID_KEM:
            break;
        case CRYPT_EAL_OPERAID_HASH:
            *algInfos = kaeMds;
            break;
        case CRYPT_EAL_OPERAID_MAC:
            break;
        case CRYPT_EAL_OPERAID_KDF:
            break;
        case CRYPT_EAL_OPERAID_RAND:
            break;
        default:
            ret = CRYPT_NOT_SUPPORT;
            break;
    }
    return ret;
}

static void CRYPT_EAL_DefaultProvFree(void *provCtx)
{
    (void) provCtx;
}

static CRYPT_EAL_Func defProvOutFuncs[] = {
    {CRYPT_EAL_PROVCB_QUERY, CRYPT_EAL_DefaultProvQuery},
    {CRYPT_EAL_PROVCB_FREE, CRYPT_EAL_DefaultProvFree},
    {CRYPT_EAL_PROVCB_CTRL, NULL},
    CRYPT_EAL_FUNC_END
};

int32_t CRYPT_EAL_ProviderInit(CRYPT_EAL_ProvMgrCtx *mgrCtx, BSL_Param *param,
    CRYPT_EAL_Func *capFuncs, CRYPT_EAL_Func **outFuncs, void **provCtx)
{
    *outFuncs = defProvOutFuncs;
    return 0;
}